package jp.androidgroup.chiba.androidresearch;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;

import jp.androidgroup.chiba.androidresearch.data.Occupation;
import jp.androidgroup.chiba.androidresearch.data.Place;
import jp.androidgroup.chiba.androidresearch.data.Time;
import jp.androidgroup.chiba.androidresearch.data.Use;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.telephony.TelephonyManager;

/**
 * 共通クラス
 */
public abstract class Common {
	/** ログのTAG */
	public static final String LOT_TAG = "AndroidResearch";
	/** 場所データ */
	private static LinkedHashMap<String, Place> _placeList;
	/** 時間帯データ */
	private static LinkedHashMap<String, Time> _timeList;
	/** 職業データ */
	private static LinkedHashMap<String, Occupation> _occList;
	/** 利用区分データ */
	private static LinkedHashMap<String, Use> _useList;
	/** 認証ユーザ情報 */
	private static UserInfo _userInfo;

	/**
	 * 場所データをセット
	 *
	 * @param placeList 場所データ
	 */
	public static void setPlaceList(List<Place> placeList) {
		_placeList = new LinkedHashMap<String, Place>();
		for(int i = 0;i < placeList.size();i++){
			_placeList.put(placeList.get(i).getId(), placeList.get(i));
		}
	}

	/**
	 * 場所データの取得
	 *
	 * @return 場所データ
	 */
	public static LinkedHashMap<String, Place> getPlaceList() {
		return _placeList;
	}

	/**
	 * 時間帯データをセット
	 *
	 * @param timeList 時間帯データ
	 */
	public static void setTimeList(List<Time> timeList) {
		_timeList = new LinkedHashMap<String, Time>();
		for(int i = 0;i < timeList.size();i++){
			_timeList.put(timeList.get(i).getId(), timeList.get(i));
		}
	}

	/**
	 * 時間帯データの取得
	 *
	 * @return 時間帯データ
	 */
	public static LinkedHashMap<String, Time> getTimeList() {
		return _timeList;
	}

	/**
	 * 職業データをセット
	 *
	 * @param occList 職業データ
	 */
	public static void setOccList(List<Occupation> occList) {
		_occList = new LinkedHashMap<String, Occupation>();
		for(int i = 0;i < occList.size();i++){
			_occList.put(occList.get(i).getId(), occList.get(i));
		}
	}

	/**
	 * 職業データの取得
	 *
	 * @return occList 職業データ
	 */
	public static LinkedHashMap<String, Occupation> getOccList() {
		return _occList;
	}

	/**
	 * 利用区分データをセット
	 *
	 * @param useList 利用区分データ
	 */
	public static void setUseList(List<Use> useList) {
		_useList = new LinkedHashMap<String, Use>();
		for(int i = 0;i < useList.size();i++){
			_useList.put(useList.get(i).getId(), useList.get(i));
		}
	}

	/**
	 * 利用区分データの取得
	 *
	 * @return 利用区分データ
	 */
	public static LinkedHashMap<String, Use> getUseList() {
		return _useList;
	}

	/**
	 * 現在の日時を取得
	 * @return yyMMddHHmmss形式の現在日時
	 */
	public static String getNowDate(){
		SimpleDateFormat sdf;

		sdf = new SimpleDateFormat("yyMMddHHmmss");

		return sdf.format(new Date());
	}

	/*
	 * ネットワークの状態を取得する
	 */
	public static boolean isConnected(Context context){
         ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo ni = cm.getActiveNetworkInfo();

         if( ni != null ){
             return cm.getActiveNetworkInfo().isConnected();
         }
         return false;
	}

	/**
	 * ダイアログ表示
	 *
	 * @param cont Context
	 * @param titleid タイトルリソースID
	 * @param msgid メッセージリソースID
	 * @param lister OK押下時のリスナー
	 */
	public static void showOkDialog(Context cont, int titleid, int msgid, DialogInterface.OnClickListener lister){
		// ダイアログの表示
        AlertDialog.Builder dlg;

        dlg = new AlertDialog.Builder(cont);
        dlg.setTitle(cont.getString(titleid));
        dlg.setMessage(cont.getString(msgid));
        dlg.setPositiveButton(cont.getString(R.string.l_ok), lister);
        dlg.show();
	}

	/**
     * オブジェクトのフィールド値を取得する
     * @param object    取得する対象となるオブジェクト
     * @param fieldName フィールド名
     *
     */
    @SuppressWarnings("rawtypes")
	public static Object getFieldValueByName(Object object, String fieldName) throws Exception {
    	Class cls;
    	Method method;
    	char firstChar;
    	char uFirstChar;
    	String getMethod;

        if (object == null) return null;

        cls = object.getClass();

        //フィールドのgetメソッド名を取得
        firstChar = fieldName.charAt(0);
        uFirstChar = Character.toUpperCase(firstChar);
        getMethod = "get" + fieldName.replaceFirst(String.valueOf(firstChar), String.valueOf(uFirstChar));

        //getメソッドを取得
        method = null;
        while(method == null){
        	try {
				method = cls.getMethod(getMethod);
				break;
			} catch (NoSuchMethodException e) {
				cls = cls.getSuperclass();
			}
        }
        //getメソッドを呼び出し、戻り値はフィールドの値になります

        return method.invoke(object);
    }

	/**
     * オブジェクトのフィールド値を設定する
     * @param object    対象となるオブジェクト
     * @param fieldName フィールド名
     */
    @SuppressWarnings("rawtypes")
	public static void setFieldValueByName(Object object,String fieldName,Object fieldValue) throws Exception {
    	Class cls;
    	Field field;
    	char firstChar;
    	char uFirstChar;

        if (object == null) return;

        //オブジェクトのClass取得
        cls = object.getClass();
        //文字列（フィールド名）からFieldオブジェクト取得
        firstChar = fieldName.charAt(0);
        uFirstChar = Character.toLowerCase(firstChar);

        field = null;
        while(field == null){
        	try {
        		field = cls.getDeclaredField(fieldName.replaceFirst(String.valueOf(firstChar),String.valueOf(uFirstChar)));
				break;
			} catch (NoSuchFieldException e) {
				cls = cls.getSuperclass();
			}
        }

        setFieldValueByName(cls, object, fieldName, new Class[]{field.getType()}, new Object[]{fieldValue});
    }

    /**
     * オブジェクトのフィールド値を設定する
     * @param cls クラス
     * @param object 対象となるオブジェクト
     * @param fieldName フィールド名
     * @param argTypes 引数の型
     * @param argValues 引数
     */
    @SuppressWarnings("rawtypes")
	public static void setFieldValueByName(Class cls,Object object,String fieldName,Class [] argTypes,Object [] argValues) throws Exception {
    	Method method;
    	char firstChar;
    	char uFirstChar;
    	String setMethod;

    	if (object == null) return;

        //setメソッド名
        firstChar = fieldName.charAt(0);
        uFirstChar = Character.toUpperCase(firstChar);
        setMethod = "set" + fieldName.replaceFirst(String.valueOf(firstChar), String.valueOf(uFirstChar));

        //setメソッド
        method = null;
        while(method == null){
        	try {
				method = cls.getMethod(setMethod, argTypes);
				break;
			} catch (NoSuchMethodException e) {
				cls = cls.getSuperclass();
			}
        }

        //setメソッド実行（オブジェクト、パラメータ）
        method.invoke(object, argValues);
    }

    /**
	 * 端末固有ID
	 *
	 * @param cont Context
	 * @return 端末固有ID
	 */
	public static String getTelephonyUniqId(Context cont){
		String id;
		TelephonyManager mTelephonyMgr;

		mTelephonyMgr = (TelephonyManager)cont.getSystemService(Context.TELEPHONY_SERVICE);
		id = mTelephonyMgr.getSimSerialNumber();

		if(id == null){
			id = "ai" + android.provider.Settings.Secure.ANDROID_ID;
		}else{
			id = "sn" + id;
		}

		return id;
	}

	/**
	 * 認証ユーザ情報を取得します。
	 *
	 * @return UserInfo ユーザー情報
	 */
	public static UserInfo getUserInfo(){
		return _userInfo;
	}

	/**
	 * 認証ユーザ情報を設定します。<br>
	 *
	 * @param userInfo
	 */
	public static void setUserInfo(UserInfo userInfo){
		_userInfo = userInfo;
	}
}
